from fastapi import APIRouter, Depends, Request
from starlette.responses import HTMLResponse
from tortoise.expressions import Q
from tortoise.transactions import atomic

from applications.common.render_template import templates
from applications.common.user_manager import permission_depends
from applications.utils.http import PageResponse, ResultResponse, fail_api, success_api, table_api
from applications.models import Power, Role
from applications.schemas.admin_power import PowerOutSchema
from applications.schemas.admin_role import (
    RoleEnableDisableSchema,
    RoleOutSchema,
    RolePowerSaveSchema,
    RoleQueryParams,
    RoleSaveSchema,
    RoleUpdateSchema,
)

route = APIRouter(prefix="/role", tags=["系统管理-角色管理"])


# 角色管理
@route.get(
    "/",
    name="system.role.main",
    dependencies=[Depends(permission_depends("system:role:main"))],
    response_class=HTMLResponse,
    include_in_schema=False,
)
async def main(request: Request):
    return templates.TemplateResponse("system/role/main.html", {"request": request})


# 表格数据
@route.get(
    "/data",
    dependencies=[Depends(permission_depends("system:role:main"))],
    summary="获取角色数据",
    response_model=PageResponse[RoleOutSchema],
)
async def table(params: RoleQueryParams = Depends()):
    query = Q()
    if params.role_name:
        query &= Q(name__contains=params.role_name)
    if params.role_code:
        query &= Q(code__contains=params.role_code)

    roles = await Role.filter(query).offset((params.page - 1) * params.limit).limit(params.limit).all()
    count = await Role.filter(query).count()
    return table_api(data=roles, count=count)


# 角色增加页面
@route.get(
    "/add",
    dependencies=[Depends(permission_depends("system:role:add"))],
    response_class=HTMLResponse,
    include_in_schema=False,
)
async def add(request: Request):
    return templates.TemplateResponse("system/role/add.html", {"request": request})


# 角色增加保存
@route.post(
    "/save",
    dependencies=[Depends(permission_depends("system:role:add"))],
    summary="保存角色",
    response_model=ResultResponse,
)
@atomic()
async def save(data: RoleSaveSchema):
    role_data = {
        "details": data.details,
        "enable": data.enable,
        "code": data.role_code,
        "name": data.role_name,
        "sort": data.sort,
    }

    role = Role(**role_data)
    await role.save()
    return success_api(msg="添加角色成功")


# 角色授权
@route.get(
    "/power/{pk}",
    dependencies=[Depends(permission_depends("system:role:power"))],
    response_class=HTMLResponse,
    include_in_schema=False,
)
async def power(request: Request, pk: int):
    return templates.TemplateResponse(request=request, name="system/role/power.html", context={"id": pk})


# 获取角色权限
@route.get("/getRolePower/{pk}", dependencies=[Depends(permission_depends("system:role:main"))], summary="获取角色权限")
async def get_role_power(pk: int):
    role = await Role.get_or_none(id=pk)
    if not role:
        return fail_api(msg="角色不存在")

    await role.fetch_related("powers")
    check_powers = await role.powers.all()
    check_powers_list = [cp.id for cp in check_powers]

    powers = await Power.all()
    output = []
    for power in powers:
        power_dict = PowerOutSchema.model_validate(power).model_dump(by_alias=True)
        power_dict["checkArr"] = "1" if power.id in check_powers_list else "0"
        power_dict["powerId"] = power.id
        power_dict["parentId"] = power.parent_id  # 添加parentId字段映射
        power_dict["powerName"] = power.name
        output.append(power_dict)

    res = {"data": output, "status": {"code": 200, "message": "默认"}}
    return res


# 保存角色权限
@route.put("/saveRolePower", dependencies=[Depends(permission_depends("system:role:edit"))], summary="保存角色权限")
@atomic()
async def save_role_power(data: RolePowerSaveSchema):
    power_list = data.powerIds.split(",")
    role = await Role.get_or_none(id=data.roleId)
    if not role:
        return fail_api(msg="角色不存在")

    powers = await Power.filter(id__in=[int(i) for i in power_list if i.isdigit()]).all()
    await role.powers.clear()
    await role.powers.add(*powers)

    return success_api(msg="授权成功")


# 角色编辑
@route.get(
    "/edit/{pk}",
    dependencies=[Depends(permission_depends("system:role:edit"))],
    response_class=HTMLResponse,
    include_in_schema=False,
)
async def edit(request: Request, pk: int):
    role = await Role.get_or_none(id=pk)
    if not role:
        return fail_api(msg="角色不存在")
    return templates.TemplateResponse("system/role/edit.html", {"request": request, "role": role})


# 更新角色
@route.put("/update", dependencies=[Depends(permission_depends("system:role:edit"))], summary="更新角色")
@atomic()
async def update(data: RoleUpdateSchema):
    role_data = {
        "code": data.roleCode,
        "name": data.roleName,
        "sort": data.sort,
        "enable": data.enable,
        "details": data.details,
    }

    role = await Role.get_or_none(id=data.roleId)
    if not role:
        return fail_api(msg="角色不存在")

    for key, value in role_data.items():
        setattr(role, key, value)

    await role.save()
    return success_api(msg="更新角色成功")


# 启用角色
@route.put("/enable", dependencies=[Depends(permission_depends("system:role:edit"))], summary="启用角色")
async def enable(data: RoleEnableDisableSchema):
    role = await Role.get_or_none(id=data.roleId)
    if not role:
        return fail_api(msg="角色不存在")

    if role.enable == 1:
        return fail_api(msg="角色已经启用")

    role.enable = 1
    await role.save()
    return success_api(msg="启用成功")


# 禁用角色
@route.put("/disable", dependencies=[Depends(permission_depends("system:role:edit"))], summary="禁用角色")
async def dis_enable(data: RoleEnableDisableSchema):
    role = await Role.get_or_none(id=data.roleId)
    if not role:
        return fail_api(msg="角色不存在")

    if role.enable == 0:
        return fail_api(msg="角色已经禁用")

    role.enable = 0
    await role.save()
    return success_api(msg="禁用成功")


# 角色删除
@route.delete("/remove/{pk}", dependencies=[Depends(permission_depends("system:role:remove"))], summary="删除角色")
@atomic()
async def remove(pk: int):
    role = await Role.get_or_none(id=pk)
    if not role:
        return fail_api(msg="角色不存在")

    # 清除该角色的权限关联
    await role.powers.clear()

    await role.delete()
    return success_api(msg="角色删除成功")
